import { terminate } from '../src/terminate';
import { IParams } from '../src/params';
import { SaeInterface } from '../src/sae';
import * as sinon from 'sinon';
import { expect } from 'chai';
import {
    AbortAndRollbackChangeOrderRequest,
    AbortAndRollbackChangeOrderResponse,
    AbortChangeOrderRequest,
    AbortChangeOrderResponse,
    ConfirmPipelineBatchRequest,
    ConfirmPipelineBatchResponse,
    DeployApplicationRequest,
    DeployApplicationResponse,
    DescribeApplicationConfigRequest,
    DescribeApplicationConfigResponse,
    DescribeChangeOrderRequest,
    DescribeChangeOrderResponse, DescribeChangeOrderResponseBody,
    DescribeChangeOrderResponseBodyData
} from '@alicloud/sae20190506'


const params: IParams = {
    PACKAGE: '',
    APPLICATION_ID: 'app123',
    Batch: '',
    BatchWaitTime: '',
    ReleaseType: '',
    StrategyType: '',
    USE_ACR_EE: false,
    buildJobID: 0,
    domestic: false,
    minReadyInstanceType: '',
    pipelineID: 0,
    pipelineName: '',
    projectDir: '',
    regionID: 'cn-hangzhou',
    workSpace: '',
    CHANGE_ORDER_ID: '12345',
    APP_NAME: 'my-app'
};


describe('terminate', () => {
    let mockSae: SaeInterface;
    let sandbox: sinon.SinonSandbox;
    let abortAndRollbackChangeOrderStub: sinon.SinonStub;

    beforeEach(() => {
        sandbox = sinon.createSandbox();
        abortAndRollbackChangeOrderStub = sandbox.stub();

        mockSae = {
            abortAndRollbackChangeOrder:abortAndRollbackChangeOrderStub,
        } as unknown as SaeInterface;

    });

    afterEach(() => {
        sandbox.restore();
    });

    it('should successfully terminate deployment', async () => {

        const mockResponse= new AbortAndRollbackChangeOrderResponse ({
            body: new DescribeChangeOrderResponseBody ({
                code: "200",
                message: "success"
            })
        });

        abortAndRollbackChangeOrderStub.resolves(mockResponse)

        await terminate(params, mockSae);

        expect(abortAndRollbackChangeOrderStub.calledOnce).to.be.true;
        expect(abortAndRollbackChangeOrderStub.firstCall.args[0]).to.deep.equal(new AbortAndRollbackChangeOrderRequest({ changeOrderId: '12345' }));
    });

    it('should throw an error if CHANGE_ORDER_ID is not set', async () => {
        const paramsWithoutChangeOrderId: IParams = { ...params, CHANGE_ORDER_ID: undefined };

        try {
            await terminate(paramsWithoutChangeOrderId, mockSae);
            expect.fail('Expected terminate to throw an error');
        }catch (error:any){
            expect(error.message).to.equal('CHANGE_ORDER_ID is not set in environment variables');
        }

    });

    it('should throw an error if abortAndRollbackChangeOrder fails', async () => {
        const error = new Error('Some error occurred');
        abortAndRollbackChangeOrderStub.rejects(error);

        try {
            await terminate(params, mockSae);
            expect.fail('Expected terminate to throw an error');
        }catch (e:any){
            expect(e.message).to.equal(`failed to abortAndRollbackChangeOrder: ${error}`);
        }
    });

    it('should throw an error if the response code is not 200', async () => {
        const mockResponse= new AbortAndRollbackChangeOrderResponse ({
            body: new DescribeChangeOrderResponseBody ({
                code: "500",
                message: "Service Error"
            })
        });

        abortAndRollbackChangeOrderStub.resolves(mockResponse);

        try {
            await terminate(params, mockSae);
            expect.fail('Expected terminate to throw an error');
        }catch (e:any){
            expect(e.message).to.equal(`failed to terminate the task, code: ${mockResponse.body?.code}, message: ${mockResponse.body?.message}`);
        }

    });

});
